using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Text;
using System.Reflection;
using System.Security.Cryptography;

namespace DeVetma.admin.classes
{
    public static class Utilities
    {
        public static string pieceString(string s, char d, int p, string def = null)
        {
            string[] tokens = s.Split(d);

            return tokens != null && tokens.Length > p ? tokens[p] : def;
        }

        public static string setPieceString(string s, char d, int p, string v)
        {
            string[] tokens = s.Split(d);

            if (tokens != null && p < tokens.Length && v != null)
                tokens[p] = v;

            return string.Join("" + d, tokens);
        }

        public static string subPieceString(string s, char d, int b, int e)
        {
            string[] tokens = s.Split(d);

            if (b > e || b < 0 || e >= tokens.Length)
                return "";

            return string.Join("" + d, tokens.Skip(b).Take(e - b + 1).ToArray());
        }

        public static string toTitleCase(string s, string d = "")
        {
            if (s != null)
            {
                string[] tokens = s.Split(' ');
                for (int i = 0; i < tokens.Length; ++i)
                    tokens[i] = Char.ToUpper(tokens[i][0]) + tokens[i].Substring(1);

                d = string.Join(" ", tokens);
            }

            return d;
        }

        public static string[] valuesOfCSV(string csv)
        {
            string[] tokens = csv == null ? null : csv.Split(',');

            if (tokens != null)
                for (int i = 0; i < tokens.Length; ++i)
                    tokens[i] = tokens[i].Trim();

            return tokens;
        }

        public static int countCSV(string csv)
        {
            return csv.Split(',').Length;
        }

        public static string[] redundantFreeCSV(string csv)
        {
            string[] items = Utilities.valuesOfCSV(csv);
            var d = items.Distinct();

            return d.Any() ? d.ToArray() : null;
        }

        public static string randomizeString(int len, bool includeNum = false,
            bool includeUpper = false, int numRatio = 4, int upperRatio = 4)
        {
            Random random = new Random((int)DateTime.Now.Ticks);
            string rstr = "";

            for (int i = 0; i < len; ++i)
            {
                char val = includeUpper && random.Next(1, 10) > 10 - upperRatio ?
                    (char)random.Next(65, 90) : (char)random.Next(97, 122);

                if (includeNum && random.Next(1, 10) > 10 - numRatio)
                    val = (char)random.Next(48, 57);

                rstr += "" + val;
            }

            return rstr;
        }

        public static string randomizeNumericString(int len)
        {
            Random random = new Random((int)DateTime.Now.Ticks);
            string rstr = "" + (char)random.Next(49, 57);

            for (int i = 1; i < len; ++i)
            {
                char val = (char)random.Next(48, 57);
                rstr += "" + val;
            }

            return rstr;
        }

        public static object reflectProperty(object o, string pr)
        {
            try
            {
                PropertyInfo p = (o.GetType()).GetProperty(pr);
                return p.GetValue(o, null);
            }
            catch (Exception ex)
            {
                return null;
            }
        }

        public static Dictionary<string, object> getClientRichObject(string[] props, object obj)
        {
            Dictionary<string, object> cro = new Dictionary<string, object>();

            foreach (var prop in props)
                cro[prop] = reflectProperty(obj, prop);

            return cro;
        }

        public static Dictionary<int, string> enumToDictionary(this Enum enm)
        {
            Dictionary<int, string> toReturn = new Dictionary<int, string>();
            Type t = enm.GetType();
            Array values = Enum.GetValues(t);

            foreach (var value in values)
                toReturn[(int)value] = Enum.GetName(t, value);

            return toReturn;
        }

        public static string toMd5Hash(this string str)
        {
            return getMd5Hash(MD5.Create(), str);
        }

        public static string getMd5Hash(MD5 md5Hash, string input)
        {
            // Convert the input string to a byte array and compute the hash.
            byte[] data = md5Hash.ComputeHash(Encoding.UTF8.GetBytes(input));

            // Create a new Stringbuilder to collect the bytes
            // and create a string.
            StringBuilder sBuilder = new StringBuilder();

            // Loop through each byte of the hashed data 
            // and format each one as a hexadecimal string.
            for (int i = 0; i < data.Length; i++)
            {
                sBuilder.Append(data[i].ToString("x2"));
            }

            // Return the hexadecimal string.
            return sBuilder.ToString();
        }

        public static bool verifyMd5Hash(MD5 md5Hash, string input, string hash)
        {
            // Hash the input.
            string hashOfInput = getMd5Hash(md5Hash, input);
            
            // Create a StringComparer an compare the hashes.
            StringComparer comparer = StringComparer.OrdinalIgnoreCase;

            return comparer.Compare(hashOfInput, hash) == 0;
        }

        public static List<T> ensureRs<T>(IEnumerable<T> rs)
        {
            return rs != null && rs.Any() ? rs.ToList() : new List<T>();
        }
    }

    public static class Extensions
    {
        public static string wrapString(this string str, string frontWrapper, 
            string backWrapper = null)
        {
            return frontWrapper + str + (backWrapper == null ? frontWrapper : backWrapper);
        }

        public static List<T> ensure<T>(this IEnumerable<T> enumerable)
        {
            return enumerable != null && enumerable.Any() ? enumerable.ToList() : new List<T>();
        }
    }
}